"""
输入框格式校验类，对规划输入框，和基础表输入框中的数据格式进行校验
"""
import copy
import re
from TestToolsV2.common.ActivityDatas import activityDatas
from TestToolsV2.tools.Log import Log
from TestToolsV2.view.OpenDialog import openDialog

douHao = ","  # 匹配逗号
lieBiaoFu1 = '\['  # 匹配左列表符号
lieBiaoFu2 = '\]'  # 匹配右列表符号
fuDianShu = '(-?\d+\.\d+)'  # 匹配浮点数
reward = '-?\d+,-?\d+,-?\d+'  # 匹配reward列表（不带[]符号）
# rewardspa = '-?\d+,-?\d+ -?\d+'  # 匹配规划reward源格式列表（不带[]符号）
# rewardlis = '\[-?\d*,-?\d*,-?\d*\]'  # 匹配reward列表（带[]符号）
# rewardPT1 = '-?\d+,-?\d+ -?\d+\s\d+\s\d+'  # 规划输入框匹配包含折扣和限购
# rewardPT2 = '\]\]\s\d+\s\d+'  # 基础表输入框匹配包含折扣和限购
zhongWen = '[\u4e00-\u9fa5]'
feiShuZi = '[^0-9,]+'
teSuFuHao1 = '[=?!@#$%^&*()_+:"<>/\\`~——，。、《》？；’：“【】、{}|·！￥…（）-]'  # 匹配各种标点符号
teSuFuHao2 = '[=.?!@#$%^&*()_+:"<>/\\`~——，。、《》？；’：“【】、{}|·！￥…（）-]'  # 匹配各种标点符号(包括.)

log = Log()


class checkForm:
    """
    验证规划和基础表输入格式是否正确
    """

    def __init__(self, _activityDatas: activityDatas):
        self.activityDatas = _activityDatas

    def PrintData(self):
        log.Show("----------------------checkForm----------------------")
        log.Show(self.activityDatas.isCosts, 20, "isCosts")
        log.Show(self.activityDatas.reEditText, 20, "reEditText")
        log.Show(self.activityDatas.taEditText, 20, "taEditText")
        log.Show(self.activityDatas.reTitles, 20, "reTitles")
        log.Show(self.activityDatas.taTitles, 20, "taTitles")
        log.Show(self.activityDatas.my_reTitle, 20, "my_reTitle")
        log.Show(self.activityDatas.my_taTitle, 20, "my_taTitle")
        log.Show(self.activityDatas.taTitleDic, 20, "taTitleDic")
        log.Show(self.activityDatas.reTitleDic, 20, "reTitleDic")
        log.Show(self.activityDatas.info, 20, "info")

    def do_checkForm(self):
        """
        执行规划和基础表输入格式验证\n
        验证没问题返回 True
        """
        # 将字符串分割成行列表
        taDataList = self.activityDatas.taEditText.splitlines()
        # 将带行头字段的列表复制一份，用来后面进行格式校验时使用
        taCheckList = copy.deepcopy(taDataList)
        # 拿出第一行，获取字段位置，规划返回字典，基础表返回布尔值
        self.activityDatas.taTitleDic, self.activityDatas.my_taTitle = self.__taTitleIndex(taDataList.pop(0))

        if self.activityDatas.reEditText:
            reDataList = self.activityDatas.reEditText.splitlines()
            reCheckList = copy.deepcopy(reDataList)
            self.activityDatas.reTitleDic, self.activityDatas.my_reTitle = self.__reTitleIndex(reDataList.pop(0))
            # 判断行数是否一致
            offset_x = len(reDataList) - len(taDataList)  # 获取长度差异值
            if offset_x != 0:  # 行数不一致时
                if offset_x > 0:  # 如果大于0说明比对源行数多
                    self.activityDatas.info.append(f'【规划】比 基础表 多 {abs(offset_x)} 行!')
                else:
                    self.activityDatas.info.append(f'【基础表】比 规划 多 {abs(offset_x)} 行!')
            self.__CheckRe(reCheckList)  # 执行比对 源 格式自查

        self.__checkTa(taCheckList)  # 执行比对 目标 格式自查

        # self.PrintData()

        if self.activityDatas.info:
            openDialog().showMessage('\n'.join(self.activityDatas.info))
            return False
        else:
            return True

    def __CheckRe(self, lineList: list):
        """
        检查规划输入格式是否正确\n
        :param lineList: 规划字符串行列表
        """
        # 提取行头，并移除列表行头
        title = lineList.pop(0)

        # 1.通过空格将行头进行分割，获取列表长度，列表长度最短不可少于2
        myTitle = title.split()
        titleLength = len(myTitle)
        titleKey = True

        if self.activityDatas.isCosts:
            if titleLength < 4:
                self.activityDatas.info.append(
                    f'titleLength_Erro:【规划】 行头字段数量少于4:【{titleLength}】,字段至少包含 [道具/奖励：数量，消耗：数量]'
                )
                titleKey = False
        else:
            if titleLength < 2:
                self.activityDatas.info.append(
                    f'titleLength_Erro:【规划】 行头字段数量少于2:【{titleLength}】,字段至少包含 [道具/奖励：数量]'
                )
                titleKey = False

        if not titleKey:
            return

        # 2.先判断行头是否有道具，数量，再判断道具和数量的个数是否一致（仅行头）
        t = 0
        c = 0
        h = 0
        for item in myTitle:
            if self.activityDatas.my_reTitle in item:
                t += 1
            if '消耗' in item:
                h += 1
            if '数量' in item:
                c += 1
        if t == 0:
            self.activityDatas.info.append(
                f'titleLength_Erro:【规划】 缺少”道具/奖励“字段，字段至少包含 [道具/奖励：数量]'
            )
            titleKey = False
        if c == 0:
            self.activityDatas.info.append(
                f'titleLength_Erro:【规划】 缺少”数量“字段，字段至少包含 [道具/奖励：数量]'
            )
            titleKey = False
        # 3.如果存在消耗，判断道具+消耗的个数是否与数量的个数一致（仅行头）
        if self.activityDatas.isCosts:
            if h == 0:
                self.activityDatas.info.append(
                    f'titleLength_Erro:【规划】 缺少”消耗“字段，字段至少包含 [道具/奖励：数量，消耗：数量]'
                )
                titleKey = False
            else:
                if (t + h) > c:
                    self.activityDatas.info.append(
                        f'titleLength_Erro:【规划】 ”数量“字段的个数不正确，字段必须成对 [道具/奖励：数量，消耗：数量]'
                    )
                    titleKey = False
        else:
            if t > c:
                self.activityDatas.info.append(
                    f'titleLength_Erro:【规划】 ”数量“字段的个数不正确，字段必须成对 [道具/奖励：数量]'
                )
                titleKey = False

        if not titleKey:
            return

        x = 0
        for line in lineList:
            x = x + 1

            # 4.通过空格将行数据进行分割，获取列表长度，列表长度最短不可少于2
            myText = line.split()
            lineLength = len(myText)
            if lineLength < 2:
                self.activityDatas.info.append(
                    f'length_Erro:【规划】第{x}行 字段数量少于2:【{lineLength}】'
                )
            # 5.判断每行的长度是否一致，如果不一致，最长不可超过行头长度，如果有消耗，最短不可少于4
            if titleLength < lineLength:
                self.activityDatas.info.append(
                    f'length_Erro:【规划】第{x}行 字段数量【{lineLength}】大于行头字段数量【{titleLength}】'
                )
            if self.activityDatas.isCosts:
                if lineLength < 4:
                    self.activityDatas.info.append(
                        f'titleLength_Erro:【规划】第{x}行 字段数量小于4：【{lineLength}】'
                    )
            # 6.判断是否存在特殊符号
            fuHaoKey = False
            fuHaoList = []
            for myitem in myText:
                zhongWenList = re.findall(zhongWen, myitem)
                if not zhongWenList:
                    teSuFuHaoList = re.findall(teSuFuHao1, myitem)
                    if teSuFuHaoList:
                        fuHaoKey = True
                        fuHaoList.append(''.join(teSuFuHaoList))
            if fuHaoKey:
                self.activityDatas.info.append(
                    f'fuHao_Erro:【规划】第{x}行 存在特殊符号【{"".join(fuHaoList)}】,请检查'
                )

            # 7.判断是否存在小数
            myCount = []
            fuDianShuList = []
            for tRewards in self.activityDatas.reTitleDic['rewards']:
                if tRewards:
                    myCount.append(tRewards[1])
            if self.activityDatas.isCosts:
                for tCosts in self.activityDatas.reTitleDic['costs']:
                    if tCosts:
                        myCount.append(tCosts[1])
            if myCount:
                for myIndex in myCount:
                    if len(myText) > myIndex:
                        fuDianShuTempList = re.findall(fuDianShu, myText[myIndex])
                        if fuDianShuTempList:
                            fuDianShuList.append(''.join(fuDianShuTempList))
            if fuDianShuList:
                self.activityDatas.info.append(
                    f'fuDianShu_Erro:【规划】第{x}行 数量字段存在小数:【{"".join(fuDianShuList)}】'
                )

    def __checkTa(self, lineList):
        """
        检查基础表输入格式是否正确\n
        :param lineList: 基础表字符串行列表
        """

        # 提取行头，并移除列表行头
        title = lineList.pop(0)

        # 获取行头 rewards和costs下标
        if 'rewards' in self.activityDatas.taTitleDic:
            rewardsIndex = self.activityDatas.taTitleDic['rewards']
        else:
            self.activityDatas.info.append(f'title_Erro:【基础表】 缺少”rewards“字段')
            return

        costsIndex = None
        if self.activityDatas.isCosts:
            if 'costs' in self.activityDatas.taTitleDic:
                costsIndex = self.activityDatas.taTitleDic['costs']
            else:
                self.activityDatas.info.append(
                    f'title_Erro:【基础表】 缺少”costs“字段'
                )
                return

                # 1.通过空格将行头进行分割，获取列表长度，列表长度最短不可少于1
        myTitle = title.split()
        titleLength = len(myTitle)
        if titleLength < 1:
            self.activityDatas.info.append(
                f'titleLength_Erro:【基础表】 字段数量错误:【{titleLength}】,字段至少包含 [rewards]'
            )
            return
        # 如过勾选了消耗，字段数量不可少于2
        if self.activityDatas.isCosts:
            if titleLength < 2:
                self.activityDatas.info.append(
                    f'titleLength_Erro:【基础表】 字段数量少于2:【{titleLength}】,字段至少包含 [rewards，costs]'
                )
                return
        # 2.先判断行头是否有道具，数量，再判断道具和数量的个数是否一致（仅行头）
        t = 0
        h = 0
        for item in myTitle:
            if self.activityDatas.my_taTitle in item:
                t += 1
            if 'costs' in item:
                h += 1
        if t == 0:
            self.activityDatas.info.append(
                f'title_Erro:【基础表】 缺少”rewards“字段'
            )
        # 如果存在消耗，判断道具+消耗的个数是否与数量的个数一致（仅行头）
        if self.activityDatas.isCosts:
            if h == 0:
                self.activityDatas.info.append(
                    f'title_Erro:【基础表】 缺少”costs“字段'
                )

        x = 0
        for line in lineList:
            x = x + 1
            lengthKey = True
            # 3.通过空格将行数据进行分割，获取列表长度，列表长度最短不可少于1
            myText = line.split()
            lineLength = len(myText)
            if lineLength < 1:
                self.activityDatas.info.append(
                    f'length_Erro:【基础表】第{x}行 字段数量少于1:【{lineLength}】'
                )
                lengthKey = False
            # 4.判断每行的长度是否一致，如果不一致，最长不可超过行头长度，如果有消耗，最短不可少于2
            if titleLength < lineLength:
                self.activityDatas.info.append(
                    f'length_Erro:【基础表】第{x}行 字段数量【{lineLength}】大于行头字段数量【{titleLength}】'
                )
            if self.activityDatas.isCosts:
                if lineLength < 2:
                    self.activityDatas.info.append(
                        f'titleLength_Erro:【基础表】第{x}行 字段数量小于2：【{lineLength}】'
                    )
                    lengthKey = False

            # 5.判断中括号是否成对
            liebiaofu1list = re.findall(lieBiaoFu1, line)
            liebiaofu2list = re.findall(lieBiaoFu2, line)
            if len(liebiaofu1list) != len(liebiaofu2list):
                self.activityDatas.info.append(f'kuoHao_Erro:【基础表】第{x}行 中括号” [ ] “对数不正确！')

            # 6.判断是否存在空格
            konggeList = []
            for myItem in myText:
                if ' ' in myItem:
                    konggeList.append(myItem)
            if konggeList:
                self.activityDatas.info.append(f'kongGe_Erro:【基础表】第{x}行 列表:{"".join(konggeList)} 存在空格！')

            if lengthKey:
                if len(myText) < rewardsIndex + 1:
                    self.activityDatas.info.append(
                        f'rewardsIndex_Erro:【基础表】第{x}行 rewards列表不存在，请检查头部字段位置是否与下方列表位置一致！'
                    )
                    return
                else:
                    if self.activityDatas.isCosts:
                        if len(myText) < costsIndex + 1:
                            self.activityDatas.info.append(
                                f'costsIndex_Erro:【基础表】第{x}行 costs列表不存在，请检查头部字段位置是否与下方列表位置一致！'
                            )
                            return

                # 7.判断是否存在非数字
                feiShuZiList = []
                rewardList = re.findall(reward, myText[rewardsIndex])
                if rewardList:
                    for rewardItem in rewardList:
                        feiShuZiTemp = re.findall(feiShuZi, rewardItem)
                        if feiShuZiTemp:
                            feiShuZiList.append(''.join(feiShuZiTemp))
                if feiShuZiList:
                    self.activityDatas.info.append(
                        f'feiShuZi_Erro:【基础表】第{x}行 rewards列表{myText[rewardsIndex]}存在非数字内容【{"".join(feiShuZiList)}】'
                    )

                if self.activityDatas.isCosts:
                    feiShuZiList.clear()
                    costsList = re.findall(reward, myText[costsIndex])
                    if costsList:
                        for costsItem in costsList:
                            feiShuZiTemp = re.findall(feiShuZi, costsItem)
                            if feiShuZiTemp:
                                feiShuZiList.append(''.join(feiShuZiTemp))
                    if feiShuZiList:
                        self.activityDatas.info.append(
                            f'feiShuZi_Erro:【基础表】第{x}行 costs列表{myText[costsIndex]}存在非数字内容【{"".join(feiShuZiList)}】'
                        )

                # 8.判断是否存在小数
                fuDianShuKey = True
                fuDianShuList = re.findall(fuDianShu, myText[rewardsIndex])
                if fuDianShuList:
                    self.activityDatas.info.append(
                        f'fuDianShu_Erro:【基础表】第{x}行 taTitles 列表中存在小数:【{"".join(fuDianShuList)}】'
                    )
                    fuDianShuKey = False
                if self.activityDatas.isCosts:
                    fuDianShuList = re.findall(fuDianShu, myText[costsIndex])
                    if fuDianShuList:
                        self.activityDatas.info.append(
                            f'fuDianShu_Erro:【基础表】第{x}行 costs 列表中存在小数:【{"".join(fuDianShuList)}】'
                        )
                        fuDianShuKey = False

                # 9.判断是否存在特殊符号
                fuHaoList = []
                fuHaoKey = True
                teSuFuHaoTemp = teSuFuHao1
                if fuDianShuKey:
                    teSuFuHaoTemp = teSuFuHao2

                for myitem in myText:
                    # 判断是否存在中文，如果存在中文，允许有特殊符号
                    zhongWenList = re.findall(zhongWen, myitem)
                    if not zhongWenList:
                        teSuFuHaoList = re.findall(teSuFuHaoTemp, myitem)
                        if teSuFuHaoList:
                            fuHaoKey = False
                            fuHaoList.append(''.join(teSuFuHaoList))
                if not fuHaoKey:
                    self.activityDatas.info.append(
                        f'fuHao_Erro:【基础表】第{x}行 存在特殊符号【{"".join(fuHaoList)}】,请检查')

                if fuDianShuKey and fuHaoKey:
                    # 10.提取出逗号检查逗号数量是否正确，逗号的数量 = length * 2 + length - 1
                    douHaoList = re.findall(douHao, myText[rewardsIndex])
                    valueLength = len(re.findall(reward, myText[rewardsIndex]))
                    if (valueLength * 2 + valueLength - 1) != len(douHaoList):
                        self.activityDatas.info.append(
                            f'douHaoErro:【基础表】第{x}行 rewards列表的 "," 数量【{len(douHaoList)}】不正确')
                    if self.activityDatas.isCosts:
                        douHaoList = re.findall(douHao, myText[costsIndex])
                        valueLength = len(re.findall(reward, myText[costsIndex]))
                        if (valueLength * 2 + valueLength - 1) != len(douHaoList):
                            self.activityDatas.info.append(
                                f'douHaoErro:【基础表】第{x}行 costs列表的 "," 数量【{len(douHaoList)}】不正确')

    def __reTitleIndex(self, _str):
        """
        获取规划字段下标\n
        :param _str: 规划行头
        :return: 返回字典{rewards:[[道具/奖励下标，数量下标],...],costs:[[消耗下标，数量下标],...]}
        """
        strList = _str.split()
        rewardTitle = []
        costTitle = []
        titleIndexDic = {'rewards': rewardTitle, 'costs': costTitle}
        length = len(strList)
        myReward = None

        for source_reward in self.activityDatas.reTitles:
            if source_reward in _str:
                if myReward:
                    if myReward != source_reward:
                        self.activityDatas.info.append(f"规划抬头中存在多个代表道具的字段【{myReward}】【{source_reward}】")
                else:
                    myReward = source_reward

        if not myReward:
            self.activityDatas.info.append(f"规划抬头中缺少代表道具的字段【{self.activityDatas.reTitles}】")
            myReward = ""

        for x in range(length):
            if myReward in strList[x]:
                for y in range(length):
                    if y > x:
                        if "数量" in strList[y]:
                            titleIndexDic['rewards'].append([x, y])
                            break
                        else:
                            if y == length:
                                titleIndexDic['rewards'].append([x, -1])
            if self.activityDatas.isCosts:
                if "消耗" in strList[x]:
                    for y in range(length):
                        if y > x:
                            if "数量" in strList[y]:
                                titleIndexDic['costs'].append([x, y])
                                break
                            else:
                                if y == length:
                                    titleIndexDic['costs'].append([x, -1])

        return titleIndexDic, myReward

    def __taTitleIndex(self, _str):
        """
        获取基础表 costs，taTitles 的位置\n
        :param _str:基础表行头
        :return:返回字典{'rewards': 下标, 'costs': 下标}
        """
        strList = _str.split()
        titleIndexDic = {}
        myReward = None
        for x in range(len(strList)):
            for target_reward in self.activityDatas.taTitles:
                if target_reward in strList[x]:
                    titleIndexDic['rewards'] = x
                    myReward = target_reward
                    break
        for x in range(len(strList)):
            if 'costs' in strList[x]:
                titleIndexDic['costs'] = x
                break
        if not myReward:
            self.activityDatas.info.append("基础表中无表示rewards的相关字段")

        return titleIndexDic, myReward
